home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 10 - 1994 / 10.04 Apr 94 / Getting Started / PixMapper.c next >
Encoding:
C/C++ Source or Header  |  1994-01-11  |  12.8 KB  |  635 lines  |  [TEXT/KAHL]

  1. /********************************/
  2. /*                                */
  3. /*  PixMapper code is            */
  4. /*    Copyright 1992, Dave Mark    */
  5. /*    All Rights Reserved            */
  6. /*                                */
  7. /********************************/
  8.  
  9. #include <QDOffscreen.h>
  10. #include <Picker.h>
  11. #include <GestaltEqu.h>
  12.  
  13. #define kMBARResID            128
  14. #define kSleep                0L
  15. #define    kMoveToFront        (WindowPtr)-1L
  16. #define    kEmptyString        "\p"
  17. #define    kEmptyTitle            kEmptyString
  18. #define    kVisible            true
  19. #define    kNoGoAway            false
  20. #define    kNilRefCon            (long)nil
  21. #define kErrorAlertID        128
  22. #define kNilFilterProc        nil
  23.  
  24. #define kSquareSize            16
  25.  
  26. #define kForegroundPICT        128
  27. #define kIgnored            nil
  28. #define kUseMaxDepth        0
  29. #define kNoFlags            (GWorldFlags)0
  30.  
  31. #define mApple                128
  32. #define iAbout                1
  33.  
  34. #define mFile                129
  35. #define iRedraw                1
  36. #define iQuit                3
  37.  
  38. #define mColors                131
  39. #define iUseRGB                1
  40. #define iUseHSV                2
  41. #define iRed                4
  42. #define iGreen                5
  43. #define iBlue                6
  44. #define iHue                4
  45. #define iSaturation            5
  46. #define iBrightness            6
  47.  
  48. // Big Debugging thanks to Stu Mark and Bill Mohler
  49.  
  50. /*************/
  51. /*  Globals  */
  52. /*************/
  53.  
  54. Boolean            gDone;
  55. Boolean            gIsRGB = true, gRandomReds = true, gRandomGreens = true, gRandomBlues = true;
  56. Boolean            gRandomHue = true, gRandomSaturation = true, gRandomBrightness = true;
  57. WindowPtr        gMainWindow;
  58. short            gXBump = 1, gYBump = 1; // <--Try changing these numbers
  59. GWorldPtr        gPictWorld, gSaveWorld, gSaveMixWorld;
  60. PixMapHandle    gPixMapSave, gPixMapSaveMix, gPixMapPict;
  61. Rect            gSavedFloaterRect, gPictWorldRect, gWorldRect;
  62. short            gGlobalHue;
  63.  
  64. /*
  65.  * Exercise: Add update handling - When you get an update, regen the
  66.  *                 screen (randomly), resave the rect behind the floater,
  67.  *                and redraw the floater...
  68.  */
  69.  
  70.  
  71. /***************/
  72. /*  Functions  */
  73. /***************/
  74.  
  75. void        ToolboxInit( void );
  76. void        MenuBarInit( void );
  77. Boolean        HasGWorlds( void );
  78. void        WindowInit( void );
  79. void        PaintWindow( void );
  80. void        RandomForeColor( void );
  81. void        GWorldInit( void );
  82. GWorldPtr     MakeGWorld( Rect *boundsPtr );
  83. void        EventLoop( void );
  84. void        DoEvent( EventRecord *eventPtr );
  85. void        HandleMouseDown( EventRecord *eventPtr );
  86. void        HandleMenuChoice( long menuChoice );
  87. void        HandleAppleChoice( short item );
  88. void        HandleFileChoice( short item );
  89. void        HandleColorsChoice( short item );
  90. void        MainLoop( void );
  91. void        DrawFirstFloater( void );
  92. void        MoveFloater( void );
  93. void        CalcNewFloaterPosition( void );
  94. void        DoError( Str255 errorString );
  95.  
  96.  
  97. /****************** main ***************************/
  98.  
  99. void    main( void )
  100. {
  101.     ToolboxInit();
  102.     MenuBarInit();
  103.     
  104.     if ( ! HasGWorlds() )
  105.         DoError( "\pDeep GWorlds not supported by this machine!" );
  106.     
  107.     WindowInit();
  108.     GWorldInit();
  109.  
  110.     DrawFirstFloater();
  111.     
  112.     EventLoop();
  113. }
  114.  
  115.  
  116. /****************** ToolboxInit *********************/
  117.  
  118. void    ToolboxInit( void )
  119. {
  120.     InitGraf( &thePort );
  121.     InitFonts();
  122.     InitWindows();
  123.     InitMenus();
  124.     TEInit();
  125.     InitDialogs( NULL );
  126.     InitCursor();
  127. }
  128.  
  129.  
  130. /****************** MenuBarInit ***********************/
  131.  
  132. void    MenuBarInit( void )
  133. {
  134.     Handle            menuBar;
  135.     MenuHandle        menu;
  136.     
  137.     menuBar = GetNewMBar( kMBARResID );
  138.     SetMenuBar( menuBar );
  139.  
  140.     menu = GetMHandle( mApple );
  141.     AddResMenu( menu, 'DRVR' );
  142.     
  143.     DrawMenuBar();
  144. }
  145.  
  146.  
  147. /****************** HasGWorlds *****************/
  148.  
  149. Boolean    HasGWorlds( void )
  150. {
  151.     long            feature;
  152.     OSErr            err;
  153.     
  154.     err = Gestalt( gestaltQuickdrawFeatures, &feature );
  155.     
  156.     if ( err != noErr )
  157.         DoError( "\pError calling Gestalt!" );
  158.     
  159.     if ( feature & 0x0004 )
  160.         return true;
  161.     else
  162.         return false;
  163. }
  164.  
  165.  
  166. /****************** WindowInit ***********************/
  167.  
  168. void    WindowInit( void )
  169. {
  170.     Rect        r;
  171.     
  172.     r = screenBits.bounds;
  173.     r.top += GetMBarHeight();
  174.     
  175.     gMainWindow = NewCWindow( nil, &r, kEmptyTitle,
  176.                     kVisible, plainDBox, kMoveToFront,
  177.                     kNoGoAway, kNilRefCon );
  178.  
  179.     SetPort( gMainWindow );
  180.     
  181.     PaintWindow();
  182. }
  183.  
  184.  
  185. /****************** PaintWindow ***********************/
  186.  
  187. void    PaintWindow( void )
  188. {
  189.     Rect        r;
  190.     short        row, col, numRows, numCols;
  191.     
  192.     SetPort( gMainWindow );
  193.     
  194.     r = gMainWindow->portRect;
  195.     
  196.     numCols = (r.right - r.left) / kSquareSize;
  197.     if ( numCols != numCols/kSquareSize*kSquareSize )
  198.         numCols++;
  199.         
  200.     numRows = (r.bottom - r.top) / kSquareSize;
  201.     if ( numRows != numRows/kSquareSize*kSquareSize )
  202.         numRows++;
  203.     
  204.     GetDateTime( (unsigned long *)(&randSeed) );
  205.     
  206.     gGlobalHue = Random();
  207.     
  208.     for ( row=0; row<numRows; row++ )
  209.         for ( col=0; col<numCols; col++ )
  210.         {
  211.             r.top = row * kSquareSize;
  212.             r.bottom = r.top + kSquareSize;
  213.             r.left = col * kSquareSize;
  214.             r.right = r.left + kSquareSize;
  215.             RandomForeColor();
  216.             PaintRect( &r );
  217.         }
  218.  
  219.     ForeColor( blackColor );
  220.     BackColor( whiteColor );
  221. }
  222.  
  223.  
  224. /****************** RandomForeColor ***********************/
  225.  
  226. void    RandomForeColor( void )
  227. {
  228.     RGBColor    color;
  229.     HSVColor    hsvColor;
  230.     
  231.     if ( gIsRGB )
  232.     {
  233.         if ( gRandomReds )
  234.             color.red = Random();
  235.         else
  236.             color.red = 0;
  237.             
  238.         if ( gRandomGreens )
  239.             color.green = Random();
  240.         else
  241.             color.green = 0;
  242.             
  243.         if ( gRandomBlues )
  244.             color.blue = Random();
  245.         else
  246.             color.blue = 0;
  247.         
  248.         RGBForeColor( &color );
  249.     }
  250.     else
  251.     {
  252.         if ( gRandomHue )
  253.             hsvColor.hue = Random();
  254.         else
  255.             hsvColor.hue = gGlobalHue;
  256.         
  257.         if ( gRandomSaturation )
  258.             hsvColor.saturation = Random();
  259.         else
  260.             hsvColor.saturation = 65535;
  261.         
  262.         if ( gRandomBrightness )
  263.             hsvColor.value = Random();
  264.         else
  265.             hsvColor.value = 65535;
  266.         
  267.         HSV2RGB( &hsvColor, &color );
  268.         RGBForeColor( &color );
  269.     }
  270. }
  271.  
  272.  
  273. /****************** GWorldInit ***********************/
  274.  
  275. void    GWorldInit( void )
  276. {
  277.     PicHandle        pic;
  278.     
  279.     pic = GetPicture( kForegroundPICT );
  280.  
  281.     if ( pic == nil )
  282.         DoError( "\pError loading PICT..." );
  283.  
  284. // Call HNoPurge() if your PICT is purgeable
  285.     
  286.     gPictWorldRect = (**pic).picFrame;
  287.     OffsetRect( &gPictWorldRect, - gPictWorldRect.left, - gPictWorldRect.top );
  288.     
  289.     gWorldRect = gPictWorldRect;
  290.     gWorldRect.bottom += 2;
  291.     gWorldRect.right += 2;
  292.     
  293.     gPictWorld = MakeGWorld( &gPictWorldRect );
  294.     gSaveWorld = MakeGWorld( &gWorldRect );
  295.     gSaveMixWorld = MakeGWorld( &gWorldRect );
  296.     
  297.     gPixMapPict = GetGWorldPixMap( gPictWorld );
  298.     gPixMapSave = GetGWorldPixMap( gSaveWorld );
  299.     gPixMapSaveMix = GetGWorldPixMap( gSaveMixWorld );
  300.  
  301. // Lock pixels before you draw or read from PixMap
  302. // Unlock when you are done. We're leaving the whole thing locked
  303. // to avoid the hassle. In a real program, do it right.
  304.  
  305.     if ( ! LockPixels( gPixMapPict ) )
  306.         DoError( "\pLockPixels failed..." );
  307.  
  308.     if ( ! LockPixels( gPixMapSave ) )
  309.         DoError( "\pLockPixels failed..." );
  310.  
  311.     if ( ! LockPixels( gPixMapSaveMix ) )
  312.         DoError( "\pLockPixels failed..." );
  313.         
  314.     SetGWorld( gPictWorld, kIgnored );
  315.         
  316.     DrawPicture( pic, &gPictWorldRect );
  317. }
  318.  
  319.  
  320. /*********************************** MakeGWorld */
  321.  
  322. GWorldPtr MakeGWorld( Rect *boundsPtr )
  323. {
  324.     QDErr        err;
  325.     GWorldPtr    newGWorld;
  326.     
  327.     err = NewGWorld( &newGWorld, kUseMaxDepth,
  328.                 boundsPtr, kIgnored, kIgnored, noNewDevice );
  329.  
  330. // In the real world, call DisposeGWorld() when you are done with the GWorld...
  331.                 
  332.     if ( err != noErr )
  333.         DoError( "\pMy call to NewGWorld died!  Bye..." );
  334.     
  335.     return( newGWorld );
  336. }
  337.  
  338.  
  339. /************************************* EventLoop */
  340.  
  341. void    EventLoop( void )
  342. {        
  343.     EventRecord        event;
  344.     
  345.     gDone = false;
  346.     while ( gDone == false )
  347.     {
  348.         if ( WaitNextEvent( everyEvent, &event, kSleep, NULL ) )
  349.             DoEvent( &event );
  350.         MoveFloater();
  351.     }
  352. }
  353.  
  354.  
  355. /************************************* DoEvent */
  356.  
  357. void    DoEvent( EventRecord *eventPtr )
  358. {
  359.     char    theChar;
  360.     
  361.     switch ( eventPtr->what )
  362.     {
  363.         case mouseDown: 
  364.             HandleMouseDown( eventPtr );
  365.             break;
  366.         case keyDown:
  367.         case autoKey:
  368.             theChar = eventPtr->message & charCodeMask;
  369.             if ( (eventPtr->modifiers & cmdKey) != 0 ) 
  370.                 HandleMenuChoice( MenuKey( theChar ) );
  371.             break;
  372.         case updateEvt:
  373.             BeginUpdate( (WindowPtr)(eventPtr->message) );
  374.             EndUpdate( (WindowPtr)(eventPtr->message) );
  375.             break;
  376.     }
  377. }
  378.  
  379.  
  380. /************************************* HandleMouseDown */
  381.  
  382. void    HandleMouseDown( EventRecord *eventPtr )
  383. {
  384.     WindowPtr        window;
  385.     short            thePart;
  386.     long            menuChoice;
  387.     
  388.     thePart = FindWindow( eventPtr->where, &window );
  389.     
  390.     switch ( thePart )
  391.     {
  392.         case inMenuBar:
  393.             menuChoice = MenuSelect( eventPtr->where );
  394.             HandleMenuChoice( menuChoice );
  395.             break;
  396.         case inSysWindow : 
  397.             SystemClick( eventPtr, window );
  398.             break;
  399.     }
  400. }
  401.  
  402.  
  403. /************************************* HandleMenuChoice */
  404.  
  405. void    HandleMenuChoice( long menuChoice )
  406. {
  407.     short    menu;
  408.     short    item;
  409.     
  410.     if ( menuChoice != 0 )
  411.     {
  412.         menu = HiWord( menuChoice );
  413.         item = LoWord( menuChoice );
  414.         
  415.         switch ( menu )
  416.         {
  417.             case mApple:
  418.                 HandleAppleChoice( item );
  419.                 break;
  420.             case mFile:
  421.                 HandleFileChoice( item );
  422.                 break;
  423.             case mColors:
  424.                 HandleColorsChoice( item );
  425.                 break;
  426.         }
  427.         HiliteMenu( 0 );
  428.     }
  429. }
  430.  
  431.  
  432. /************************************* HandleAppleChoice */
  433.  
  434. void    HandleAppleChoice( short item )
  435. {
  436.     MenuHandle    appleMenu;
  437.     Str255        accName;
  438.     short        accNumber;
  439.     
  440.     switch ( item )
  441.     {
  442.         case iAbout:
  443.             SysBeep( 20 );
  444.             break;
  445.         default:
  446.             appleMenu = GetMHandle( mApple );
  447.             GetItem( appleMenu, item, accName );
  448.             accNumber = OpenDeskAcc( accName );
  449.             break;
  450.     }
  451. }
  452.  
  453.  
  454. /************************************* HandleFileChoice */
  455.  
  456. void    HandleFileChoice( short item )
  457. {
  458.     switch ( item )
  459.     {
  460.         case iRedraw:
  461.             PaintWindow();
  462.             DrawFirstFloater();
  463.             break;
  464.         case iQuit:
  465.             gDone = true;
  466.             break;
  467.     }
  468. }
  469.  
  470.  
  471. /************************************* HandleColorsChoice */
  472.  
  473. void    HandleColorsChoice( short item )
  474. {
  475.     MenuHandle        menu;
  476.     
  477.     menu = GetMenu( mColors );
  478.     
  479.     if ( item == iUseRGB )
  480.     {
  481.         gIsRGB = true;
  482.         
  483.         SetItem( menu, iRed, "\pRandom Reds" );
  484.         SetItem( menu, iGreen, "\pRandom Greens" );
  485.         SetItem( menu, iBlue, "\pRandom Blues" );
  486.         
  487.         CheckItem( menu, iUseRGB, true );
  488.         CheckItem( menu, iUseHSV, false );
  489.         CheckItem( menu, iRed, gRandomReds );
  490.         CheckItem( menu, iGreen, gRandomGreens );
  491.         CheckItem( menu, iBlue, gRandomBlues );
  492.     }
  493.     else if ( item == iUseHSV )
  494.     {
  495.         gIsRGB = false;
  496.         
  497.         SetItem( menu, iHue, "\pRandom Hue" );
  498.         SetItem( menu, iSaturation, "\pRandom Saturation" );
  499.         SetItem( menu, iBrightness, "\pRandom Brightness" );
  500.         
  501.         CheckItem( menu, iUseRGB, false );
  502.         CheckItem( menu, iUseHSV, true );
  503.         CheckItem( menu, iHue, gRandomHue );
  504.         CheckItem( menu, iSaturation, gRandomSaturation );
  505.         CheckItem( menu, iBrightness, gRandomBrightness );
  506.     }
  507.     else if ( gIsRGB )
  508.     {
  509.         switch ( item )
  510.         {
  511.             case iRed:
  512.                 gRandomReds = !gRandomReds;
  513.                 CheckItem( menu, iRed, gRandomReds );
  514.                 break;
  515.             case iGreen:
  516.                 gRandomGreens = ! gRandomGreens;
  517.                 CheckItem( menu, iGreen, gRandomGreens );
  518.                 break;
  519.             case iBlue:
  520.                 gRandomBlues = ! gRandomBlues;
  521.                 CheckItem( menu, iBlue, gRandomBlues );
  522.                 break;
  523.         }
  524.     }
  525.     else
  526.     {
  527.         switch ( item )
  528.         {
  529.             case iHue:
  530.                 gRandomHue = !gRandomHue;
  531.                 CheckItem( menu, iHue, gRandomHue );
  532.                 break;
  533.             case iSaturation:
  534.                 gRandomSaturation = ! gRandomSaturation;
  535.                 CheckItem( menu, iSaturation, gRandomSaturation );
  536.                 break;
  537.             case iBrightness:
  538.                 gRandomBrightness = ! gRandomBrightness;
  539.                 CheckItem( menu, iBrightness, gRandomBrightness );
  540.                 break;
  541.         }
  542.     }
  543.     PaintWindow();
  544.     DrawFirstFloater();
  545. }
  546.  
  547.  
  548. /****************** DrawFirstFloater *********************/
  549.  
  550. void    DrawFirstFloater( void )
  551. {
  552.     CopyBits( &(gMainWindow->portBits), (BitMap *)(*gPixMapSave),
  553.         &gWorldRect, &gWorldRect, srcCopy, nil );
  554.     
  555.     gSavedFloaterRect = gPictWorldRect;
  556.     OffsetRect( &gSavedFloaterRect, 1, 1 );
  557.  
  558.     CopyBits( (BitMap *)(*gPixMapPict), &(gMainWindow->portBits),
  559.         &gPictWorldRect, &gSavedFloaterRect, transparent, nil );
  560. }
  561.  
  562.  
  563. /****************** MoveFloater *********************/
  564.  
  565. void    MoveFloater( void )
  566. {
  567.     Rect        r;
  568.     RgnHandle    newRgn, savedRgn, oldClip;
  569.  
  570.     CalcNewFloaterPosition();
  571.     
  572.     CopyBits( (BitMap *)(*gPixMapSave), (BitMap *)(*gPixMapSaveMix),
  573.         &gWorldRect, &gWorldRect, srcCopy, nil );
  574.     
  575.     r = gPictWorldRect;
  576.     OffsetRect( &r, gXBump + 1, gYBump + 1 );
  577.     
  578.     CopyBits( (BitMap *)(*gPixMapPict), (BitMap *)(*gPixMapSaveMix),
  579.         &gPictWorldRect, &r, transparent, nil );
  580.     
  581.     r = gSavedFloaterRect;
  582.     InsetRect( &r, -1, -1 );
  583.     
  584.     CopyBits( (BitMap *)(*gPixMapSaveMix), &(gMainWindow->portBits),
  585.         &gWorldRect, &r, srcCopy, nil );
  586.     
  587.     OffsetRect( &gSavedFloaterRect, gXBump, gYBump );
  588.     
  589.     r = gSavedFloaterRect;
  590.     InsetRect( &r, -1, -1 );
  591.     
  592.     CopyBits( &(gMainWindow->portBits), (BitMap *)(*gPixMapSaveMix),
  593.         &r, &gWorldRect, srcCopy, nil );
  594.     
  595.     r = gWorldRect;
  596.     OffsetRect( &r, -gXBump, -gYBump );
  597.     
  598.     CopyBits( (BitMap *)(*gPixMapSave), (BitMap *)(*gPixMapSaveMix),
  599.         &gWorldRect, &r, srcCopy, nil );
  600.     
  601.     CopyBits( (BitMap *)(*gPixMapSaveMix), (BitMap *)(*gPixMapSave),
  602.         &gWorldRect, &gWorldRect, srcCopy, nil );
  603. }
  604.  
  605.  
  606. /*********************************** CalcNewFloaterPosition */
  607.  
  608. void    CalcNewFloaterPosition( void )
  609. {
  610.     Rect    r;
  611.     
  612.     r = gSavedFloaterRect;
  613.     
  614.     OffsetRect( &r, gXBump, gYBump );
  615.     
  616.     if ( (r.left < gMainWindow->portRect.left) ||
  617.         ( r.right > gMainWindow->portRect.right ) )
  618.         gXBump *= -1;
  619.     
  620.     if ( (r.top < gMainWindow->portRect.top) ||
  621.         ( r.bottom > gMainWindow->portRect.bottom ) )
  622.         gYBump *= -1;
  623. }
  624.  
  625.  
  626. /***************** DoError ********************/
  627.  
  628. void    DoError( Str255 errorString )
  629. {
  630.     ParamText( errorString, kEmptyString, kEmptyString, kEmptyString );
  631.     
  632.     StopAlert( kErrorAlertID, kNilFilterProc );
  633.     
  634.     ExitToShell();
  635. }